
import {Injectable} from "@angular/core";
import {
    Canvas,
    Map,
    Marker,
    CircleMarker,
    Polyline,
    Polygon,
    Icon,
    FeatureGroup,
    PM
} from 'leaflet';
import { ConfigService } from "src/app/shared/services/config.service";
import { FeatureService } from "src/app/shared/services/feature.service";

@Injectable()
export class LayerService {
    private _layers: any = [
        {
            "_id": 1,
            "name": "商店",
            "geotype": 1,
            "style": {
                "type": 1,
                "iconUrl": 'assets/images/map/商店.svg',
                "iconSize": [20, 20],
                "iconAnchor": [10, 20]
            },
            "fields": ["编码", "名称"],
            "visible": true,
            "active": false,
            "labeled": false,
            "label": {
                "field": "名称"
            }
        },
        {
            "_id": 2,
            "name": "餐饮",
            "geotype": 1,
            "style": {
                "type": 1,
                "iconUrl": 'assets/images/map/餐饮.svg',
                "iconSize": [20, 20],
                "iconAnchor": [10, 20]
            },
            "fields": ["编码", "名称"],
            "visible": true,
            "active": false,
            "labeled": false,
            "label": {
                "field": "名称"
            }
        },
        {
            "_id": 3,
            "name": "银行",
            "geotype": 1,
            "style": {
                "type": 1,
                "iconUrl": 'assets/images/map/银行.svg',
                "iconSize": [20, 20],
                "iconAnchor": [10, 20]
            },
            "fields": ["编码", "名称"],
            "visible": true,
            "active": false,
            "labeled": false,
            "label": {
                "field": "名称"
            }
        },
        {
            "_id": 4,
            "name": "医务",
            "geotype": 1,
            "style": {
                "type": 1,
                "iconUrl": 'assets/images/map/医务.svg',
                "iconSize": [20, 20],
                "iconAnchor": [10, 20]
            },
            "fields": ["编码", "名称"],
            "visible": true,
            "active": false,
            "labeled": false,
            "label": {
                "field": "名称"
            }
        },
        {
            "_id": 5,
            "name": "充电",
            "geotype": 1,
            "style": {
                "type": 1,
                "iconUrl": 'assets/images/map/充电.svg',
                "iconSize": [20, 20],
                "iconAnchor": [10, 20]
            },
            "fields": ["编码", "名称"],
            "visible": true,
            "active": false,
            "labeled": false,
            "label": {
                "field": "名称"
            }
        },
        {
            "_id": 101,
            "name": "建筑",
            "geotype": 3,
            "style": {
                "color": "#ffb980",
                "fillColor": "#ffb980",
                "fillOpacity": 0.8
            },
            "fields": ["编码", "名称", "楼栋"],
            "visible": true,
            "active": true,
            "labeled": false,
            "label": {
                "field": "名称"
            }
        },
        {
            "_id": 102,
            "name": "绿地",
            "geotype": 3,
            "style": {
                "color": "#7eb00a",
                "fillColor": "#7eb00a",
                "fillOpacity": 0.8
            },
            "fields": ["编码", "名称", "面积"],
            "visible": true,
            "active": false,
            "labeled": false,
            "label": {
                "field": "名称"
            }
        },
        {
            "_id": 103,
            "name": "水面",
            "geotype": 3,
            "style": {
                "color": "#5ab1ef",
                "fillColor": "#5ab1ef",
                "fillOpacity": 0.8
            },
            "fields": ["编码", "名称", "面积"],
            "visible": true,
            "active": false,
            "labeled": false,
            "label": {
                "field": "名称"
            }
        },
        {
            "_id": 104,
            "name": "道路",
            "geotype": 3,
            "style": {
                "color": "#8d98b3",
                "weight": 5,
                "fillColor": "#8d98b3",
                "fillOpacity": 0.9
            },
            "fields": ["编码", "名称"],
            "visible": true,
            "active": false,
            "labeled": false,
            "label": {
                "field": "名称"
            }
        }
    ];

    private _created: any = [];
    private _deleted: any = [];
    private _updated: any = [];

    map: Map;
    popup: any;

    constructor(private featureService: FeatureService, private configService: ConfigService) {
    }

    get layers() {
        return this._layers;
    }

    add(layer) {
        if (!this.has(layer)) {
            this._layers.push(layer);
        }
    }

    remove(layer) {
        const index = this._layers.findIndex(item => item._id === layer._id);
        index != -1 && this._layers.splice(index, 1);
    }

    has(layer) {
        return this._layers.find(item => item._id === layer._id);
    }

    clear() {
        this._layers = [];
    }

    count() {
        return this._layers.length;
    }

    init(map, popup) {
        this.map = map;
        this.popup = popup;
        this.map.pm.removeControls();
        this._layers.forEach(item => {
            item.group = new FeatureGroup();
            item.group.addTo(map);
            if (item.active) {
                item.group.pm.setOptions({
                    allowEditing: true,
                    allowRemoval: true,
                    allowCutting: true,
                    allowRotation: true
                });
                if (item.geotype == 1) {
                    if (item.style.type == 1) {
                        this.map.pm.setGlobalOptions({
                            markerStyle: {
                              icon: new Icon(item.style)
                            }
                        } as any);
                        this.map.pm.addControls({  
                            position: 'topleft',  
                            drawMarker: true, 
                            drawCircleMarker: false,
                            drawPolyline: false,
                            drawRectangle: false,
                            drawPolygon: false,
                            drawCircle: false
                        }); 
                    } else {
                        this.map.pm.setPathOptions(item.style);
                        this.map.pm.addControls({  
                            position: 'topleft',  
                            drawMarker: false, 
                            drawCircleMarker: true,
                            drawPolyline: false,
                            drawRectangle: false,
                            drawPolygon: false,
                            drawCircle: false
                        }); 
                    }
                } else if (item.geotype == 2){
                    this.map.pm.setPathOptions(item.style);
                    this.map.pm.addControls({  
                        position: 'topleft',  
                        drawMarker: false, 
                        drawCircleMarker: false,
                        drawPolyline: true,
                        drawRectangle: false,
                        drawPolygon: false,
                        drawCircle: false
                    }); 
                } else {
                    this.map.pm.setPathOptions(item.style);
                    this.map.pm.addControls({  
                        position: 'topleft',  
                        drawMarker: false, 
                        drawCircleMarker: false,
                        drawPolyline: false,
                        drawRectangle: true,
                        drawPolygon: true,
                        drawCircle: true
                    }); 
                }
                this.map.pm.setGlobalOptions({
                    layerGroup: item.group
                } as any);
            } else {
                item.group.pm.setOptions({
                    allowEditing: false,
                    allowRemoval: false,
                    allowCutting: false,
                    allowRotation: false
                });
            }
            this.featureService.getLayer(item.name).subscribe( res => {
                if (Array.isArray(res)) {
                    res.forEach(feature => {
                        if (item.geotype == 1) {
                            if(feature.geometry.type === 'Point'){
                                let marker;
                                if(item.style.type == 1) {
                                    marker = new Marker([feature.geometry.coordinates[1],feature.geometry.coordinates[0]],{
                                        icon: new Icon(item.style)
                                    });
                                } else {
                                    marker = new CircleMarker([feature.geometry.coordinates[1],feature.geometry.coordinates[0]], item.style);
                                }                               
                                item.group.addLayer(marker);
                                (marker as any)._id = feature._id;
                                (marker as any).layer = item.name;
                                (marker as any).properties = feature.properties;
                                marker.on('pm:edit', this.handleUpdate.bind(this));
                            }
                        } else if (item.geotype == 2) {
                            if(feature.geometry.type === 'LineString'){
                                const swap = feature.geometry.coordinates.map( point => [point[1],point[0]] ) ;
                                const polyline = new Polyline(swap);
                                item.group.addLayer(polyline);
                                (polyline as any)._id = feature._id;
                                (polyline as any).layer = item.name;
                                (polyline as any).properties = feature.properties;
                                polyline.on('pm:edit', this.handleUpdate.bind(this));
                            }
                        } else {
                            if(feature.geometry.type === 'Polygon'){
                                const swap = feature.geometry.coordinates.map( ring => ring.map( point => [point[1],point[0]]));
                                const polygon = new Polygon(swap);
                                item.group.addLayer(polygon);
                                (polygon as any)._id = feature._id;
                                (polygon as any).layer = item.name;
                                (polygon as any).properties = feature.properties;
                                polygon.on('pm:edit', this.handleUpdate.bind(this));
                            }
                        }
                    });
                    item.group.setStyle(item.style);
                    item.group.pm.setOptions({
                        allowEditing: item.active,
                        allowRemoval: item.active,
                        allowCutting: item.active,
                        allowRotation: item.active
                    });
                    item.group.on('click', this.handleClick.bind(this));
                }
            });
        });
        this.map.on('pm:create', this.handleCreate.bind(this));
        this.map.on('pm:remove', this.handleDelete.bind(this));
        
    }

    handleClick(e) {
        this.popup && this.popup.show(e.layer);
    }

    handleCreate(e) {
        const active = this._layers.find(item => item.active);
        if (!active) return;
        (e.layer as any).created = true;
        (e.layer as any).layer = active.name;
        (e.layer as any)._id = this.configService.guid();
        this._created.push({
            _id: (e.layer as any)._id,
            layer: active.name,
            geometry: (e.layer as any).toGeoJSON().geometry
        });
        e.layer.on('pm:edit', this.handleUpdate.bind(this));
    }
    handleDelete(e) {
        if ((e.layer as any).created) {
            const index = this._created.findIndex(feature => feature._id == (e.layer as any)._id);
            this._created.splice(index, 1);
        } else if ((e.layer as any).updated) {
            const index = this._updated.findIndex(feature => feature._id == (e.layer as any)._id);
            this._updated.splice(index, 1);
        } else {
            this._deleted.push({
                _id: (e.layer as any)._id
            });
        }
    }
    handleUpdate(e) {
        if ((e.layer as any).created) {
            const created = this._created.find(feature => feature._id == (e.layer as any)._id);
            if (created) {
                created.geometry = (e.layer as any).toGeoJSON().geometry;
            }
        } else {
            (e.layer as any).updated = true;
            const updated = this._updated.find(feature => feature._id == (e.layer as any)._id);
            if (updated) {
                updated.geometry = (e.layer as any).toGeoJSON().geometry;
            } else {
                this._updated.push({
                    _id: (e.layer as any)._id,
                    geometry: (e.layer as any).toGeoJSON().geometry
                });
            }
        }
    }

    active(layer) {
        this._layers.forEach(item => {
            if (item._id != layer._id) {
                item.active = false;
                item.group.pm.setOptions({
                    allowEditing: false,
                    allowRemoval: false,
                    allowCutting: false,
                    allowRotation: false
                });
            }
        });
        this.map.pm.removeControls();
        layer.active = true;
        layer.group.pm.setOptions({
            allowEditing: true,
            allowRemoval: true,
            allowCutting: true,
            allowRotation: true
        });
        if (layer.geotype == 1) {
            if (layer.style.type == 1) {
                this.map.pm.setGlobalOptions({
                    markerStyle: {
                      icon: new Icon(layer.style)
                    }
                } as any);
                this.map.pm.addControls({  
                    position: 'topleft',  
                    drawMarker: true, 
                    drawCircleMarker: false,
                    drawPolyline: false,
                    drawRectangle: false,
                    drawPolygon: false,
                    drawCircle: false
                }); 
            } else {
                this.map.pm.setPathOptions(layer.style);
                this.map.pm.addControls({  
                    position: 'topleft',  
                    drawMarker: false, 
                    drawCircleMarker: true,
                    drawPolyline: false,
                    drawRectangle: false,
                    drawPolygon: false,
                    drawCircle: false
                }); 
            }
        } else if (layer.geotype == 2){
            this.map.pm.setPathOptions(layer.style);
            this.map.pm.addControls({  
                position: 'topleft',  
                drawMarker: false, 
                drawCircleMarker: false,
                drawPolyline: true,
                drawRectangle: false,
                drawPolygon: false,
                drawCircle: false
            }); 
        } else {
            this.map.pm.setPathOptions(layer.style);
            this.map.pm.addControls({  
                position: 'topleft',  
                drawMarker: false, 
                drawCircleMarker: false,
                drawPolyline: false,
                drawRectangle: true,
                drawPolygon: true,
                drawCircle: true
            }); 
        }
         
        this.map.pm.setGlobalOptions({
            layerGroup: layer.group
        } as any);
    }

    deactive(layer) {
        layer.active = false;
        layer.group.pm.setOptions({
            allowEditing: false,
            allowRemoval: false,
            allowCutting: false,
            allowRotation: false
        });
        this.map.pm.removeControls();
    }

    switch(layer) {
        if (layer.visible) {
            layer.group.addTo(this.map);
        } else {
            if (layer.active) this.deactive(layer);
            layer.group.removeFrom(this.map);
        }
    }

    save() {
        this.featureService.bulk(this._created, this._deleted, this._updated).subscribe(res => {
            this._created = [];
            this._deleted = [];
            this._updated = [];
            this._layers.forEach(item => {
                item.group.eachLayer(layer => {
                    (layer as any).created = undefined;
                    (layer as any).deleted = undefined;
                    (layer as any).updated = undefined;
                });
            })
        });
    }

    label(layer) {
        layer.labeled = true;
        if (layer.visible) {
            layer.group.eachLayer(item => {
                item.properties && item.bindTooltip(item.properties[layer.label.field], { permanent: true });
            });
        }
    }

    unlabel(layer) {
        layer.labeled = false;
        layer.group.eachLayer(item => {
            item. unbindTooltip();
        });
    }

}
